package com.pwc.soapUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;

public class SoapUtil {

	private static String nonceKey = "OmOwyXPaJvaeiYnr1oUQoQ==";

	/**
	 * main sending function
	 * 
	 * @param message
	 * @param url
	 * @return
	 * @throws UnsupportedOperationException
	 * @throws SOAPException
	 * @throws IOException
	 */
	public String sendNormalSoap(String message, String url)
			throws UnsupportedOperationException, SOAPException, IOException {
		return SendSoapBase(message,url,null,null,"None");
	}

	public String SendPasswordTextSoap(String message, String url,
			String userName, String password)
			throws UnsupportedOperationException, SOAPException, IOException {
		return SendSoapBase(message, url, userName, password, "passwordText");
	}

	public String SendSoapBase(String message, String url, String userName,
			String password, String passwordType)
			throws UnsupportedOperationException, SOAPException, IOException {
		SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory
				.newInstance();
		SOAPConnection soapConnection = soapConnectionFactory
				.createConnection();
		SOAPMessage SoapMessage = getMessage(message);

		if ("passwordText".equalsIgnoreCase(passwordType)) {
			SoapMessage = addSecurity(SoapMessage, userName, password);
		}

		SOAPMessage soapResponse = soapConnection.call(SoapMessage, url);
		soapConnection.close();
		String result = getResponseToString(soapResponse);

		return result;
	}

	private String getResponseToString(SOAPMessage soapResponse)
			throws SOAPException, IOException {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		soapResponse.writeTo(stream);
		String result = new String(stream.toByteArray(), "utf-8");
		return result;
	}

	/**
	 * 
	 * @param send
	 * @return
	 * @throws IOException
	 * @throws SOAPException
	 */
	private static SOAPMessage getMessage(String send) throws IOException,
			SOAPException {
		InputStream is = new ByteArrayInputStream(send.getBytes());
		SOAPMessage request = MessageFactory.newInstance().createMessage(null,
				is);
		return request;
	}

	private static SOAPMessage addSecurity(SOAPMessage soapMessage,
			String userName, String password) throws SOAPException {

		SOAPHeader header = soapMessage.getSOAPHeader();

		SOAPElement security = header
				.addChildElement(
						"Security",
						"wsse",
						"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

		SOAPElement usernameToken = security.addChildElement("UsernameToken",
				"wsse");
		usernameToken
				.addAttribute(
						new QName("xmlns:wsu"),
						"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

		SOAPElement userNamePart = usernameToken.addChildElement("Username",
				"wsse");
		userNamePart.addTextNode(userName);

		SOAPElement passwordPart = usernameToken.addChildElement("Password",
				"wsse");
		passwordPart
				.setAttribute(
						"Type",
						"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
		passwordPart.addTextNode(password);

		SOAPElement nonce = usernameToken.addChildElement("Nonce", "wsse");
		nonce.setAttribute(
				"EncodingType",
				"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary");
		nonce.addTextNode(nonceKey);

		SOAPElement created = usernameToken.addChildElement("Created", "wsse");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
		Calendar c1 = Calendar.getInstance();
		created.addTextNode(sdf.format(c1.getTime()));

		return soapMessage;
	}

}
